/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.commons.event;


import io.iec.edp.caf.commons.event.config.EventListenerData;
import io.iec.edp.caf.commons.event.config.EventListenerSettings;
import io.iec.edp.caf.commons.event.config.EventManagerData;
import io.iec.edp.caf.commons.event.entity.*;
import io.iec.edp.caf.commons.exception.CAFRuntimeException;
import io.iec.edp.caf.commons.utils.InvokeService;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;

/**
 * 事件总管
 * 一个模块事件管理的外观，提供事件管理的集中访问
 * @author lijing
 * @date 2019/9/4 16:07
 */
public abstract class EventBroker {
    /**
     * 事件监听配置实体
     */
    @Autowired
    private EventListenerSettings eventListenerSettings;

    /**
     * 是否已初始化
     */
    private Boolean initialzied = false;
    /**
     * 事件管理者集合
     */
    protected EventManagerCollection eventManagerCollection;


    /**
     * 获取事件管理者集合
     * @return  事件管理者集合
     */
    protected EventManagerCollection getEventManagerCollection(){
        return this.eventManagerCollection;
    }

    /**
     * 构造函数
     */
    @Deprecated
    protected EventBroker(){
        this.eventManagerCollection = new EventManagerCollection();
    }

    /**
     * 构造函数
     */
    protected EventBroker(EventListenerSettings settings){
        this.eventManagerCollection = new EventManagerCollection();
        this.eventListenerSettings = settings;
    }


    /**
     * 获取指定的事件监听者对象配置
     * @param managerName 事件配置编码
     * @return 事件监听者对象配置
     */
    public List<EventListenerData> getEventListenerDataList(String managerName){
        List<EventManagerData> list = this.eventListenerSettings.getEventManagers();
        if(list==null || list.size() ==0)
            return null;
        for(EventManagerData data :list){
            if(data.getName().equals(managerName))
                return data.getListeners();
        }
        return null;
    }

    /**
     * 初始化
     */
    public void init(){
        //此处纯粹为兼容写法
        if(this.initialzied && this.eventManagerCollection.count()>0) return;
        this.onInit();
        for (int index = 0; index < this.eventManagerCollection.count(); index++){
            EventManager manager = this.eventManagerCollection.get(index);
            List<EventListenerData> eventListenerDataList= this.getEventListenerDataList(manager.getEventManagerName());
            if(eventListenerDataList!=null&&eventListenerDataList.size()!=0){
                for(EventListenerData eventListenerData:eventListenerDataList){
                    IEventListener eventListener=this.createEventListener(eventListenerData);
                    this.registListener(manager, eventListener);
                }
            }
        }
        this.initialzied = true;
    }

    /**
     * 子类进行初始化时必须覆写此方法
     */
    protected abstract void onInit();

    /**
     * 创建IEventListener
     * @param eventListenerData 监听器数据
     * @return IEventListener
     */
    protected IEventListener createEventListener(EventListenerData eventListenerData){
        String notDefineCode = "Undefined Code";
        IEventListener eventListener=null;
        try{
            if(eventListenerData==null){
                this.handlingError(EventError.ListenerConfigNotExist,  notDefineCode);
            }

            // 检查类名称是否已经指定。
            if (eventListenerData.getImplClassName()== null || eventListenerData.getImplClassName().trim().equals("")) {
                this.handlingError(EventError.ListenerClassInvalid,eventListenerData.getName());
            }

            Class<?> clazz=null;
            //获取类
            try{
                //本类为系统级jar包 由默认的LaunchedURLClassLoader加载 此处需传入线程持有的类加载器(CAFClassLoader) 否则getImplClassName对应的类LaunchedURLClassLoader可能不可见 会抛出ClassNotFoundException
                clazz = InvokeService.getClass(eventListenerData.getImplClassName());
            }catch(Exception e){
                this.handlingError(EventError.ListenerClassNotFound, e, eventListenerData.getName());
            }
            //指定的类必须实现IEventListener接口，没有实现就抛出异常
            if(!IEventListener.class.isAssignableFrom(clazz)){
                this.handlingError(EventError.ListenerClassNotImplInterface, eventListenerData.getName());
            }
            try{
                //创建对象 并返回
                eventListener= (IEventListener)clazz.newInstance();
            }catch(Exception e){
                this.handlingError(EventError.InstantiationOfImplementationClassFailed,eventListenerData.getName());
            }
        }catch (Exception e){
            if(eventListenerData==null){
                handlingError(EventError.ListenerUnIdentify, e, notDefineCode);
            }else{
                handlingError(EventError.ListenerUnIdentify, e, eventListenerData.getName());
            }
        }
        return eventListener;
    }

    /**
     * 注册事件监听者
     * @param eventListener 事件监听者
     */
    private void registListener(EventManager manager,IEventListener eventListener) {
        if (manager.isHandlerListener(eventListener)) {
            manager.addListener(eventListener);
        }
    }

    /**
     * 注册事件监听者
     * @param eventListener 事件监听者
     */
    protected void registListener(IEventListener eventListener) {

    }

    /**
     * 注册事件监听者
     * @param eventListener 事件监听者
     */
    protected void removeListener(IEventListener eventListener) {
        EventManager manager = null;
        for (int index = 0; index < this.eventManagerCollection.count(); index++) {
            manager = this.getEventManagerCollection().get(index);
            if (manager.isHandlerListener(eventListener) == false) {
                continue;
            }
            manager.removeListener(eventListener);
        }
    }

    /**
     * 错误
     * @param error 错误枚举
     * @param errorParams 参数
     */
    private void handlingError(EventError error,Object... errorParams){
        handlingError(error, null, errorParams);
    }

    /**
     * 处理错误
     * @param errorCode 错误枚举
     * @param internalException  异常
     * @param errorParams 参数
     */
    private void handlingError(EventError errorCode, Exception internalException, Object... errorParams) {
        if (internalException != null && internalException instanceof CAFRuntimeException){
            CAFRuntimeException cafRuntimeException=(CAFRuntimeException)internalException;
            throw cafRuntimeException;
        }
        EventErrorDefinition error = new EventErrorDefinition(errorCode, errorParams);
        //TODO-异常变化，暂时如下处理
        throw new CAFRuntimeException("caf",error.getErrorCode(),error.getErrorMessage(),internalException);
        //ErrorHandling.HandlingError(error, internalException);
    }

}
